<template>
  <div class="content-wrap matching-wrapper">
    <div class="content-box">
      <div class="content-left">
        <div class="top-box">
          <Card>
            <div slot="title" class="tit">表具匹配监控范围漏斗图</div>
            <div class="chart-box">
              <h-funnel3d :fetchData="getLoudouData" :defaultOptions="hFunnel3dOptions" :chartData="lodouData" />
              <Spin fix v-show="hFunnel3dLoading">加载中...</Spin>
            </div>
          </Card>
        </div>
        <div class="bottom-box">
          <Card>
            <div slot="title" class="tit">表具/流量不匹配饼图</div>
            <div class="chart-box">
              <h-pie3d :defaultOptions="hPie3dOptions" :fetchData="getPieData" :chartData="pieData" />
              <Spin fix v-show="hPie3dLoading">加载中...</Spin>
            </div>
          </Card>
        </div>
      </div>
      <div class="content-right">
        <div class="top-box">
          <div class="top-box-left">
            <Card>
              <div slot="title" class="tit">表具/流量匹配关系二维树图</div>
              <div class="chart-box">
                <e-treemap :chartData="guanxiData" @q-click="rectTreeMapClickHandle" />
                <Spin fix v-show="guanxiLoading">加载中...</Spin>
              </div>
            </Card>
          </div>
          <div class="top-box-right">
            <Card>
              <div slot="title" class="tit clearfix">
                <span class="fl">表具/流量不匹配详图</span>
                <Select class="fr" placeholder="表模型" size="small" v-model="meterModel" style="width: 100px;">
                  <Option v-for="(item, index) in meterModelList" :key="item.id" :value="index">{{
                    item.modelNoName
                  }}</Option>
                </Select>
              </div>
              <div class="chart-box">
                <h-bar3d :defaultOptions="hBar3dOptions" :chartData="barLineData" />
                <Spin fix v-show="hBar3dLoading">加载中...</Spin>
              </div>
            </Card>
          </div>
        </div>
        <div class="bottom-box box">
          <Card>
            <div slot="title" class="tit">表具/流量匹配列表</div>
            <div class="table-box fit-table-parent">
              <table-page
                :fit="true"
                :columns="columns"
                :value="tableData"
                :total="total"
                :pageNum="pageNum"
                :pageSize="pageSize"
                :loading="loading"
                @on-change-page="onChangePage"
                @on-row-dblclick="onRowDblclick"
                @on-row-click="onRowClick"
                :stripe="false"
                size="small"
                :border="false"
                :no-data-text="tableHint"
              >
              </table-page>
            </div>
          </Card>
        </div>
      </div>
      <Modal
        v-model="showTreeFlag"
        class="tree-modal"
        title="详情"
        @on-cancel="onTreeCancel"
        width="96%"
        :styles="{ top: '30px', height: '85%' }"
      >
        <div :is="userAndMeterInfoTpl" :content="meterDetailData" :currentMeterId="currentMeterId"></div>
        <div slot="footer">
          <Button @click="onTreeCancel" ghost>关闭</Button>
        </div>
      </Modal>
    </div>
  </div>
</template>
<script>
import { each, isArray, isEmpty, merge } from 'lodash'
import dayjs from 'dayjs'
import jsPlumb from 'jsplumb'
import tableMixin from '@/mixins/table'
import {
  findList,
  barLine,
  rectInfo,
  loudou,
  pieInfo,
  getMeterUnitDetail,
  getMeterModelList,
  fetchDeleteTableData
} from '@/api/meterManageMatching'
import tableColums from './tableColums'
import { hFunnel3dOptions, hPie3dOptions, eTreemapOptions, hBar3dOptions, PIE_STATUS } from './chartOptions'

export default {
  name: 'matching',
  mixins: [tableMixin],
  components: {
    HBar3d: () => import('@/commons/charts/HBar3d'),
    UserAndMeterDetailETree: () => import('@/commons/UserAndMeterDetailETree'),
    HPie3d: () => import('@/commons/charts/HPie3d'),
    ETreemap: () => import('@/commons/charts/ETreemap'),
    HFunnel3d: () => import('@/commons/charts/HFunnel3d')
  },
  data() {
    return {
      currentDate: dayjs(this.$config.nowDate).subtract(1, 'month').format('YYYY-MM'),
      showTreeFlag: false,
      tableData: [],
      pageNum: 1,
      pageSize: 20,
      total: 0,
      tableHint: '',
      loading: false,
      columns: this.renderTableColums(),
      barLineData: null,
      lodouData: null,
      pieData: null,
      guanxiData: null,
      meterGasClass: undefined,
      status: undefined,
      meterDetailData: null,
      userAndMeterInfoTpl: null,
      currentMeterId: undefined,
      rowTimer: null,
      modelMaxCount: 0,
      meterModel: undefined,
      meterModelList: [],
      hFunnel3dLoading: false,
      hPie3dLoading: false,
      guanxiLoading: false,
      hBar3dLoading: false
    }
  },
  watch: {
    meterModel() {
      if (isEmpty(this.barLineData)) {
        this.$Notice.warning({
          title: '操作提示',
          desc: '表具/流量不匹配详图没有数据，无法操作'
        })
      } else {
        this.filterMeterModel()
      }
    }
  },
  mounted() {
    this.getGuanxituData()
    this.getMeterModelListData()
  },
  computed: {
    hPie3dOptions() {
      return hPie3dOptions
    },
    hBar3dOptions() {
      return hBar3dOptions
    },
    hFunnel3dOptions() {
      return hFunnel3dOptions
    }
  },
  methods: {
    onTreeCancel() {
      this.showTreeFlag = false
      this.userAndMeterInfoTpl = null
      this.meterDetailData = null
    },
    /**
     * @msg: 漏斗图数据整理
     * @param {type}
     * @return:
     */
    modifyLoudouData(data) {
      const _serList = []
      each(data, item => {
        const { name, value } = item
        _serList.push({
          name,
          y: value
        })
      })

      this.lodouData = merge({}, hFunnel3dOptions, {
        series: [
          {
            data: _serList
          }
        ]
      })
    },
    /**
     * @msg: 获取漏斗图数据
     * @param {type}
     * @return:
     */
    async getLoudouData() {
      this.hFunnel3dLoading = true
      const { code, date } = await loudou({
        month: this.currentDate
      })
      this.hFunnel3dLoading = false
      if (code === 200) {
        this.modifyLoudouData(date)
      }
    },
    /**
     * @msg: 饼图数据整理
     * @param {type}
     * @return:
     */
    modifyPieData(data = []) {
      const _serList = []
      each(data, item => {
        if (Number(item.status)) {
          _serList.push({
            name: item.status + '',
            y: item.count
          })
        }
      })

      const _vis = !isEmpty(_serList)

      this.pieData = merge({}, hPie3dOptions, {
        series: [
          {
            animation: true,
            data: _serList,
            visible: _vis
          }
        ]
      })
    },
    /**
     * @msg: 获取饼图数据
     * @param {type}
     * @return:
     */
    async getPieData() {
      this.hPie3dLoading = true
      const { code, date } = await pieInfo({
        month: this.currentDate
      })
      this.hPie3dLoading = false
      if (code === 200) {
        this.modifyPieData(date)
      }
    },
    /**
     * @msg: 整理关系图数据
     * @param {type}
     * @return:
     */
    modifyGuanxiData(data) {
      const _result = []

      function item(arg, type) {
        const { name, value } = arg
        return {
          name: PIE_STATUS[name] || name,
          status: name,
          value,
          path: name,
          gasClass: type,
          isDone: true
        }
      }

      function items(arr, type) {
        const r = []
        each(arr, arg => {
          const { name, value, children } = arg
          if (isArray(children)) {
            r.push({
              name: PIE_STATUS[name] || name,
              status: name,
              value,
              path: name,
              children: items(children, type),
              gasClass: type
            })
          } else {
            r.push(item(arg, type))
          }
        })
        return r
      }

      each(data, d => {
        const { name, value, children = [] } = d
        _result.push({
          gasClass: name,
          name,
          value,
          children: items(children, name)
        })
      })
      this.guanxiData = merge({}, eTreemapOptions, {
        series: [
          {
            data: _result
          }
        ]
      })
    },
    /**
     * @msg:获取关系图数据
     * @param {type}
     * @return:
     */
    async getGuanxituData() {
      this.guanxiLoading = true
      const { code, date } = await rectInfo({
        month: this.currentDate
      })
      this.guanxiLoading = false
      if (code === 200) {
        this.modifyGuanxiData(date)
      }
    },
    /**
     * @msg: 整理柱状图数据
     * @param {type}
     * @return:
     */
    modifyZhuzhuangtuData(data) {
      const { hist, newDev, oldDev, maxCount } = data
      this.modelMaxCount = maxCount
      const _serList = []
      const lineArr = []
      each(hist, item => {
        const { count, min, max } = item
        _serList.push({
          name: min + '-' + max,
          y: count,
          x: max,
          min,
          max
        })
      })
      const halfOld = maxCount / 2
      if (oldDev && oldDev.qMax) {
        const oldMax = oldDev.qMax
        const oldName = oldDev.modelNoName
        lineArr.push({
          type: 'line',
          color: '#fd631e',
          name: oldName,
          data: [
            [0, halfOld],
            [oldMax, halfOld],
            [oldMax, 0]
          ]
        })
      }

      if (newDev && newDev.qMax) {
        const newMax = newDev.qMax
        const newName = newDev.modelNoName
        lineArr.push({
          type: 'line',
          color: '#32e06f',
          name: newName,
          dashStyle: 'dash',
          data: [
            [0, maxCount],
            [newMax, maxCount],
            [newMax, 0]
          ]
        })
      }

      this.barLineData = merge({}, hBar3dOptions, {
        series: [
          {
            data: _serList
          },
          ...lineArr
        ]
      })
    },
    /**
     * @msg: 获取柱状图数据
     * @param {type}
     * @return:
     */
    async getZhuzhuangtuData(month, meterId) {
      this.hBar3dLoading = true
      const { code, date } = await barLine({
        month,
        meterId
      })
      this.hBar3dLoading = false
      this.$Loading.finish()
      if (code === 200) {
        this.modifyZhuzhuangtuData(date)
      }
    },
    loadAjax() {
      const { pageNum, pageSize, currentDate, meterGasClass, status } = this
      this.tableHint = '正在刷新…'
      this.loading = true
      findList({
        month: currentDate,
        meterGasClass,
        status,
        pageNum,
        pageSize
      })
        .then(res => {
          if (res.date && res.date.list && res.date.list.length > 0) {
            const { total, list, pageNum, pageSize } = res.date
            this.total = total
            this.pageNum = pageNum
            this.pageSize = pageSize
            this.tableData = list
          } else {
            this.tableData = []
            this.tableHint = '暂无数据'
          }
          this.loading = false
        })
        .catch(() => {
          this.tableHint = '暂无数据'
          this.loading = false
        })
    },
    /**
     * @msg: 表模型列表
     * @param {type}
     * @return:
     */
    getMeterModelListData() {
      getMeterModelList().then(res => {
        if (res.date) {
          this.meterModelList = res.date
        }
      })
    },
    filterMeterModel() {
      const modelData = this.meterModelList[this.meterModel]
      const modelMax = modelData.qMax
      const modelName = modelData.modelNoName
      let flag = false
      const { series } = this.barLineData
      for (let i = 0; i < series.length; i++) {
        if (series[i].name === modelName) {
          flag = true
          break
        }
      }
      if (!flag) {
        series[3] = {
          name: modelName,
          type: 'line',
          dashStyle: 'LongDash',
          color: '#ffff43',
          data: [
            [0, this.modelMaxCount],
            [modelMax, this.modelMaxCount],
            [modelMax, 0]
          ]
        }
        this.barLineData = merge({}, hBar3dOptions, {
          series
        })
      }
    },
    /**
     * 表格行设置
     * @return {[type]} [description]
     */
    renderTableColums() {
      const lastCloums = {
        title: '操作',
        align: 'center',
        fixed: 'right',
        width: 80,
        render: (h, params) => {
          return h('div', [
            h('Button', {
              props: {
                type: 'text',
                size: 'small',
                customIcon: 'iconfont icon-delete'
              },
              attrs: {
                title: '删除'
              },
              on: {
                click: () => {
                  this.handleDelete(params.row)
                }
              }
            })
          ])
        }
      }

      return [...tableColums, lastCloums]
    },
    drawLine(data) {
      const that = this
      const { y } = data._itemLayouts[1]
      const textDom = that.$refs['bjinfotext']
      const textDomHeight = textDom.offsetHeight
      const retHeight = y - textDomHeight / 2 + 4
      textDom.style.top = retHeight + 'px'

      that.$nextTick(() => {
        if (that.jsplumb) {
          that.jsplumb.reset()
          that.jsplumb = null
        }
        that.jsplumb = jsPlumb.jsPlumb.getInstance({
          Anchor: ['Right', 'Left'],
          Anchors: ['Right', 'Left'],
          ConnectionsDetachable: false,
          Connector: 'Straight',
          PaintStyle: {
            stroke: '#7da2e1'
          },
          ConnectorStyle: {
            stroke: '#7da2e1'
          },
          EndpointStyle: {
            radius: 4,
            fillStyle: '#ffffff'
          }
        })
        that.jsplumb.ready(function() {
          that.jsplumb.connect({
            source: 'bjinfoname',
            target: 'bjinfotext',
            endpoint: 'Dot'
          })
        })
      })
    },
    rectTreeMapClickHandle(data) {
      const { isDone, gasClass, status } = data.data
      if (isDone) {
        this.meterGasClass = gasClass
        this.status = status
        this.loadAjax()
      }
    },
    /**
     * @msg: 点击行数据
     * @param {type}
     * @return:
     */
    onRowClick(row = {}, index) {
      clearTimeout(this.rowTimer)
      this.rowTimer = setTimeout(() => {
        this.$Loading.start()
        const { meterId } = row
        this.getZhuzhuangtuData(this.currentDate, meterId)
      }, 300)
    },
    /**
     * @msg: 双击行数据
     * @param {type}
     * @return:
     */
    onRowDblclick(row = {}, index) {
      clearTimeout(this.rowTimer)
      const { meterId } = row
      this.currentMeterId = meterId
      this.$Loading.start()
      getMeterUnitDetail(meterId).then(res => {
        if (res.date) {
          this.$Loading.finish()
          this.meterDetailData = res.date
          this.userAndMeterInfoTpl = 'UserAndMeterDetailETree'
          this.showTreeFlag = true
        }
      })
    },
    handleDelete(data) {
      const { meterId } = data
      this.$Modal.confirm({
        title: '操作提示',
        content: `<p>是否删除表具ID为 ${meterId} 的数据!</p>`,
        onOk: () => {
          this.deleteTableData(meterId)
        }
      })
    },
    async deleteTableData(id) {
      const { code, msg } = await fetchDeleteTableData({
        meterId: id,
        month: this.currentDate
      })
      if (code === 200) {
        this.$Message.success(msg)
        this.pageNum = 1
        this.$nextTick(() => {
          this.loadAjax()
        })
      } else {
        this.$Message.error(msg)
      }
    }
  }
}
</script>
<style scoped lang="less">
@import './index.less';
</style>
